using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sedna.Core.Common.Objects.Navigation;
using Sedna.Core.Controller;
using Sedna.Core.Security;
using Sedna.Core.Tiles.Contents;
using Sedna.Core.Tiles.Layout;

namespace Sedna.Core.Tiles.Holder
{
	/// <summary>
	/// Container for <c>PlaceHolder</c>
	/// <c>IEnumerable</c> determines the order of elements of the underlying <c>PlaceHolder</c>`s
	/// </summary>
    public class PlaceHolderContainer : Control, IContent, IEnumerable, INamingContainer, IEnabled
	{
		private IPlaceHolderContainerLayout layout;	    
		private String contentPlaceHolderId;
	    
        private IPrincipalWrapper principalWrapper;
        
	    private IList rolesVisible;
        private IList rolesEnabled;

        private bool enabled = true;

        private String enabledPath;
        private String visiblePath;

        private IScopePathParser scopePathParser;
	    

		#region Properties

		public IPlaceHolderContainerLayout Layout
		{
			get { return layout;}
			set { layout = value;}
		}

		public String ContentPlaceHolderId
		{
			get { return contentPlaceHolderId;}
			set { contentPlaceHolderId = value;}
		}

	    public bool Enabled
	    {
	        get { return enabled; }
	        set { enabled = value; }
	    }

	    public string EnabledPath
	    {
	        set { enabledPath = value; }
	    }

	    public string VisiblePath
	    {
	        set { visiblePath = value; }
	    }

	    public IScopePathParser ScopePathParser
	    {
	        set { scopePathParser = value; }
	    }

        public IPrincipalWrapper PrincipalWrapper
        {
            set { principalWrapper = value; }
        }

        public IList RolesVisible
        {
            get { return rolesEnabled; }
            set { rolesVisible = value; }
        }

        public IList RolesEnabled
        {
            get { return rolesEnabled; }
            set { rolesEnabled = value; }
        }

	    #endregion

		#region Public Members

		public PlaceHolderContainer AddPlaceHolder(PlaceHolder placeHolder)
		{
            Layout.PlaceHolders.Add(placeHolder);
			return this;
		}

		/// <summary>
		/// Force build layout of the contents
		/// </summary>
		public void BuildContent()
		{
			EnsureChildControls();
		}

		#endregion		

		#region IEnumerable

		public IEnumerator GetEnumerator()
		{
			if (Layout == null || Layout.PlaceHolders == null)
			{
				return new ArrayList(0).GetEnumerator();
			}

			return Layout.PlaceHolders.GetEnumerator();
		}

		#endregion	    	    

	    protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

           // Visible = true; // This propetry should be set in Bind() method
        }

		protected override void CreateChildControls()
		{
            if (Layout == null)
			{
				return;
			}

            if (Layout.IsSelfRender)
			{                			    
				foreach (Control control in Layout.BuildLayout())
				{                    
				    Controls.Add(control);
				}
			}
			else if (Layout.PlaceHolders != null)
			{
				foreach (PlaceHolder placeHolder in Layout)
				{
                    Controls.Add(placeHolder);
				}
			}
		}
	    
	    protected override void OnPreRender(EventArgs e)
	    {
	        base.OnPreRender(e);

            Bind();
	    }	    
	    
	    public void Bind()
	    {
            if (!String.IsNullOrEmpty(enabledPath))
            {
                Enabled = Enabled && Convert.ToBoolean(scopePathParser.Parse(enabledPath).Value);
            }

            Enabled = Enabled && IsEnabledForPrincipal();	        
            Layout.Enabled = Enabled;

	        if (!String.IsNullOrEmpty(visiblePath))
            {
                Visible = Visible && Convert.ToBoolean(scopePathParser.Parse(visiblePath).Value);
            }

            Visible = Visible && IsVisibleForPrincipal();
            Layout.Visible = Visible;
	        
	        if (Layout.PlaceHolders != null)
	        {
                foreach (PlaceHolder placeHolder in Layout)
                {
                    if (placeHolder.Parent == null)
                        placeHolder.Bind();
                }
	        }
	    }

        public bool IsVisibleForPrincipal()
        {
            //if (IsEnabledForPrincipal())
            //    return true;

            if (principalWrapper == null || rolesVisible == null || rolesVisible.Count == 0)
            {
                return true;
            }

            foreach (string roleName in rolesVisible)
            {
                if (principalWrapper.IsInRole(roleName))
                {
                    return true;
                }
            }

            /*
             * This is not the same as write in the beginning of the method:
             * 
             * if (IsEnabledForPrincipal()) return true;
             * 
             * because if visible roles exist but a principle doesn't have permissions
             * to view and edit roles haven't been set then control should be disabled
             * 
             */
            if (rolesEnabled == null || rolesEnabled.Count == 0)
            {
                return false;
            }

            return IsEnabledForPrincipal();
        }

        public bool IsEnabledForPrincipal()
        {
            if (principalWrapper == null || rolesEnabled == null || rolesEnabled.Count == 0)
            {
                return true;
            }

            foreach (string roleName in rolesEnabled)
            {
                if (principalWrapper.IsInRole(roleName))
                {
                    return true;
                }
            }

            return false;
        }
	}
}
